package com.codedancer.campus.client.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.codedancer.campus.client.service.IConfessionalWallCommentService;
import com.codedancer.campus.client.service.bo.confessionalWallComment.CommentAddBo;
import com.codedancer.campus.client.service.bo.confessionalWallComment.ConfessionalWallCommentPageSearchBo;
import com.codedancer.campus.client.service.vo.confessionalWallComment.ConfessionalWallCommentVo;
import com.codedancer.campus.common.dataresource.ExternalApiData;
import com.codedancer.campus.common.exception.BusinessException;
import com.codedancer.campus.common.utils.SensitiveWordsDetectUtil;
import com.codedancer.campus.common.utils.UUIDGenerator;
import com.codedancer.campus.enums.ConfessionalWallStatus;
import com.codedancer.campus.mapper.ConfessionalWallCommentMapper;
import com.codedancer.campus.mapper.ConfessionalWallMapper;
import com.codedancer.campus.mapper.UserMapper;
import com.codedancer.campus.po.ConfessionalWall;
import com.codedancer.campus.po.ConfessionalWallComment;
import com.codedancer.campus.po.User;
import com.codedancer.campus.qo.confessionalWallComment.ConfessionalWallCommentPageSearchQo;
import com.google.common.collect.Lists;

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(rollbackFor = Exception.class)
public class ConfessionalWallCommentServiceImpl implements IConfessionalWallCommentService {

    @Autowired
    private ConfessionalWallCommentMapper confessionalWallCommentMapper;
    @Autowired
    private ConfessionalWallMapper confessionalWallMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ExternalApiData externalApiData;

    /**
     * 表白墙评论
     *
     * @param commentAddBo
     */
    @Override
    public void add(CommentAddBo commentAddBo) {
        ConfessionalWall confessionalWall = confessionalWallMapper.findById(commentAddBo.getConfessionalWallUuid()).orElseThrow(() -> new BusinessException("表白墙不存在"));
        if (confessionalWall.getStatus().equals(ConfessionalWallStatus.PENDING_REVIEW) || confessionalWall.getStatus().equals(ConfessionalWallStatus.NOT_PASS)) {
            throw new BusinessException("表白墙处于待审核或未通过状态");
        }
        if (externalApiData.checkSensitiveWords(commentAddBo.getContent())) {
            throw new BusinessException("内容存在敏感词汇，请检查");
        }
        ConfessionalWallComment confessionalWallComment = new ConfessionalWallComment();
        confessionalWallComment.setUuid(UUIDGenerator.getUUID());
        confessionalWallComment.setCommentUserUuid(commentAddBo.getCurrentUserUuid());
        confessionalWallComment.setConfessionalWallUuid(commentAddBo.getConfessionalWallUuid());
        confessionalWallComment.setRepliedUserUuid(commentAddBo.getRepliedUserUuid());
        confessionalWallComment.setContent(commentAddBo.getContent());
        confessionalWallCommentMapper.insert(confessionalWallComment);
    }

    /**
     * 分页查询表白墙父级评论
     *
     * @param confessionalWallCommentPageSearchBo
     * @return
     */
    @Override
    public IPage<ConfessionalWallCommentVo> pageParentComment(
        ConfessionalWallCommentPageSearchBo confessionalWallCommentPageSearchBo) {
        ConfessionalWallCommentPageSearchQo confessionalWallCommentPageSearchQo = BeanUtil
            .copyProperties(confessionalWallCommentPageSearchBo,
                ConfessionalWallCommentPageSearchQo.class);
        ConfessionalWall confessionalWall = confessionalWallMapper
            .findById(confessionalWallCommentPageSearchBo.getConfessionalWallUuid())
            .orElseThrow(() -> new BusinessException("表白墙不存在"));
        IPage<ConfessionalWallComment> confessionalWallCommentIPage = null;
        if (confessionalWall.getIsOpenComment()) {
            confessionalWallCommentIPage = confessionalWallCommentMapper
                .pageParentComment(
                    new Page<ConfessionalWallComment>(confessionalWallCommentPageSearchBo.getPage(),
                        confessionalWallCommentPageSearchBo.getSize()),
                    confessionalWallCommentPageSearchQo);
        }
        IPage<ConfessionalWallCommentVo> confessionalWallCommentVoIPage = new Page<>();
        List<ConfessionalWallCommentVo> confessionalWallCommentVos = Lists.newArrayList();
        assert confessionalWallCommentIPage != null;
        if (CollectionUtil.isNotEmpty(confessionalWallCommentIPage.getRecords())) {
            confessionalWallCommentVos = confessionalWallCommentIPage.getRecords().stream()
                .map(confessionalWallComment -> {
                    ConfessionalWallCommentVo confessionalWallCommentVo = BeanUtil
                        .copyProperties(confessionalWallComment, ConfessionalWallCommentVo.class);
                    confessionalWallCommentVo.setCommentTime(confessionalWallComment.getCreateTime());
                    User user = userMapper.selectById(confessionalWallComment.getCommentUserUuid());
                    confessionalWallCommentVo.setCommentNickName(user.getNickName());
                    confessionalWallCommentVo.setCommentAvatar(user.getAvatar());
                    // 判断父级评论是否有儿子
                    confessionalWallCommentVo.setHasChildren(
                        confessionalWallCommentMapper.hasChildren(confessionalWallComment.getUuid()));
                    return confessionalWallCommentVo;
                }).collect(Collectors.toList());
        }
        confessionalWallCommentVoIPage.setRecords(confessionalWallCommentVos);
        confessionalWallCommentVoIPage.setTotal(confessionalWallCommentIPage.getTotal());
        return confessionalWallCommentVoIPage;
    }

    /**
     * 表白墙回复
     *
     * @param commentAddBo
     */
    @Override
    public void reply(CommentAddBo commentAddBo) {
        ConfessionalWallComment parentConfessionalWallComment = confessionalWallCommentMapper.findById(
                commentAddBo.getConfessionalWallCommentUuid())
            .orElseThrow(() -> new BusinessException("表白墙评论已不存在"));
        ConfessionalWallComment confessionalWallComment = new ConfessionalWallComment();
        confessionalWallComment.setUuid(UUIDGenerator.getUUID());
        confessionalWallComment.setConfessionalWallUuid(
            parentConfessionalWallComment.getConfessionalWallUuid());
        confessionalWallComment.setCommentUserUuid(commentAddBo.getCurrentUserUuid());
        confessionalWallComment.setRepliedUserUuid(commentAddBo.getRepliedUserUuid());
        // 判断该评论是否是顶级
        if (parentConfessionalWallComment.getParentUuid().equals("0")) {
            // 是顶级评论，则需要将该评论的uuid作为下一级的parentUuid
            confessionalWallComment.setParentUuid(parentConfessionalWallComment.getUuid());
        } else {
            // 否则将父级的parentUuid，最为下级的parentUuid
            confessionalWallComment.setParentUuid(parentConfessionalWallComment.getParentUuid());
        }
        confessionalWallComment.setContent(commentAddBo.getContent());
        confessionalWallCommentMapper.insert(confessionalWallComment);
    }

    /**
     * 分页查询该评论下子集评论
     *
     * @param confessionalWallCommentPageSearchBo
     * @return
     */
    @Override
    public IPage<ConfessionalWallCommentVo> pageChildrenComment(
        ConfessionalWallCommentPageSearchBo confessionalWallCommentPageSearchBo) {
        ConfessionalWallCommentPageSearchQo confessionalWallCommentPageSearchQo = BeanUtil.copyProperties(
            confessionalWallCommentPageSearchBo, ConfessionalWallCommentPageSearchQo.class);
        IPage<ConfessionalWallComment> confessionalWallCommentIPage = confessionalWallCommentMapper.pageChildrenComment(
            new Page<ConfessionalWallComment>(confessionalWallCommentPageSearchBo.getPage(),
                confessionalWallCommentPageSearchBo.getSize()),
            confessionalWallCommentPageSearchQo);
        IPage<ConfessionalWallCommentVo> confessionalWallCommentVoIPage = new Page<>();
        List<ConfessionalWallCommentVo> confessionalWallCommentVos;
        confessionalWallCommentVos = confessionalWallCommentIPage.getRecords().stream()
            .map(confessionalWallComment -> {
                ConfessionalWallCommentVo confessionalWallCommentVo = BeanUtil
                    .copyProperties(confessionalWallComment, ConfessionalWallCommentVo.class);
                confessionalWallCommentVo.setCommentTime(confessionalWallComment.getCreateTime());
                User user = userMapper.selectById(confessionalWallComment.getCommentUserUuid());
                confessionalWallCommentVo.setCommentNickName(user.getNickName());
                confessionalWallCommentVo.setCommentAvatar(user.getAvatar());
                // 判断父级评论是否有儿子
                confessionalWallCommentVo.setHasChildren(
                    confessionalWallCommentMapper.hasChildren(confessionalWallComment.getUuid()));
                // 查询被回复用户
                User repliedUser = userMapper.selectById(confessionalWallComment.getRepliedUserUuid());
                confessionalWallCommentVo.setRepliedNickName(repliedUser.getNickName());
                return confessionalWallCommentVo;
            }).collect(Collectors.toList());
        confessionalWallCommentVoIPage.setRecords(confessionalWallCommentVos);
        confessionalWallCommentVoIPage.setTotal(confessionalWallCommentIPage.getTotal());
        confessionalWallCommentVoIPage.setPages(confessionalWallCommentIPage.getPages());
        confessionalWallCommentVoIPage.setSize(confessionalWallCommentPageSearchBo.getSize());
        return confessionalWallCommentVoIPage;
    }

    /**
     * 删除评论
     *
     * @param confessionalWallCommentUuid
     */
    @Override
    public void delete(String confessionalWallCommentUuid) {
        if (!confessionalWallCommentMapper.existsByUuId(confessionalWallCommentUuid)) {
            throw new BusinessException("评论不存在");
        }
        // 将下面的子集评论全部删除
        confessionalWallCommentMapper.deleteByColumn("parent_uuid", confessionalWallCommentUuid);
        // 删除掉该评论
        confessionalWallCommentMapper.deleteById(confessionalWallCommentUuid);
    }
}
